package com.halden.mycache.support.EvictStrategy.impl;

import com.halden.mycache.support.EvictStrategy.ICacheEvictContext;
import com.halden.mycache.core.Impl.CacheValue;
import com.halden.mycache.core.Impl.MyCache;
import com.halden.mycache.support.listener.CacheRemoveContext;
import com.halden.mycache.support.listener.RemoveType;
import lombok.extern.slf4j.Slf4j;

import java.util.Date;

/**
 * @Author: halden
 * @Data:2023/2/3 18:48
 * @Description:
 */
@Slf4j
public class LRUStrategy<K,V> extends AbstractEvictStrategy<K,V> {

    /**
     * 仿照redis的LRU，随机选取5个成员，淘汰其中上次访问时间最早的
     * @param context
     * @since 0.0.1
     */
    public void evict(ICacheEvictContext<K, V> context) {
        MyCache<K, V> cache = context.getCache();
        int length = cache.getLength();
        log.info("进行内存淘汰");
        // 随机抽取内存中的5个元素
        Integer[] integers = random5Num(length);
        K[] keys = (K[]) cache.keySet().toArray();
        K key = null;
        long age = -1;
        // 遍历元素，找出其中访问时间最久的元素
        for (Integer i : integers){
            // System.out.println(cache.simpleGet(keys[i])+"进行内存淘汰");
            // 使用simpleGet不修改该元素的最后访问时间与访问频率
            CacheValue<V> cacheValue = cache.simpleGet(keys[i]);
            // 如果发现了过期元素，直接返回
            // 在checkExpire方法中已经将过期元素删除
            cache.checkExpire(keys[i], cacheValue);
            long lastUseTime = cacheValue.getLastUseTime();
            long now = new Date().getTime();
            long nAge = now - lastUseTime;
            if (nAge > age){
                age = nAge;
                key = keys[i];
            }
        }
        //已经剔除了过期元素，空间解放，无须淘汰内存
        length = cache.getLength();
        if (length < cache.getSize()){
            return;
        }
        // 将找到的元素删除，完成内存淘汰
        cache.remove(key, new CacheRemoveContext<>(key, cache.simpleGet(key).getValue(), RemoveType.EVICT_REMOVE));
    }
}

